package com.myblog.demo.common;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * 密码工具类
 * 加盐加密 / 加盐解密
 */
public class PasswordTools {

    /**
     * 加盐加密
     *
     * @param password 明文密码
     * @return 加盐加密后的密码 + 盐值
     */
    public static String encrypt(String password) {
        // 1. 产生盐值
        String salt = UUID.randomUUID().toString().replace("-", "");

        // 2. 使用盐值 + 明文密码进行加密
        String encryptPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));
        // 3. 将盐值和加密密码共同返回（通过 $ 合并）
        return salt + "$" + encryptPassword;
    }

    /**
     * 通过传入的盐值进行加密
     *
     * @param password 明文密码
     * @param salt     传入的盐值
     * @return 加盐加密后的密码 + 盐值
     */
    public static String encrypt(String password, String salt) {
        // 1. 使用盐值 + 明文密码进行加密
        String encryptPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));
        // 2. 将盐值和加密密码共同返回（通过 $ 合并）
        return salt + "$" + encryptPassword;
    }

    /**
     * 验证加盐加密密码
     *
     * @param password   用户输入的明文密码
     * @param dbPassword 数据库中储存的密码（盐值 + 加盐加密密码）
     * @return boolean
     */
    public static boolean decrypt(String password, String dbPassword) {
        // 1. 参数合法性判断
        if (!StringUtils.hasLength(password) || !StringUtils.hasLength(dbPassword)
                || dbPassword.length() != 65 || !dbPassword.contains("$")) {
            return false;
        }

        // 2. 分离盐值和加密密码
        String[] parts = dbPassword.split("\\$");
        // 2.1 得到盐值
        String salt = parts[0];
        // 2.2 得到正确密码的加盐加密密码
        String encryptPassword = parts[1];


        /* 方法一：
        String toCheckEncryptPassword = encrypt(password, salt);

        return dbPassword.equals(toCheckEncryptPassword);*/

        // 方法二：

        // 3. 对输入的密码进行加盐加密
        String encryptInputPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));

        // 4. 判断密码是否相等并返回结果
        return encryptPassword.equals(encryptInputPassword);
    }


    // Spring Security 的加盐加密
    public static void main(String[] args) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = "123456";
        String markPassword1 = passwordEncoder.encode(password);
        String markPassword2 = passwordEncoder.encode(password);
        String markPassword3 = passwordEncoder.encode(password);
        System.out.println(markPassword1);
        System.out.println(markPassword2);
        System.out.println(markPassword3);

        String inputPassword = "12356";
        boolean result = passwordEncoder.matches(inputPassword, markPassword1);
        System.out.println(result);
    }

    public static void main1(String[] args) {

        String password = "123456";

        String dbPassword1 = PasswordTools.encrypt(password);
        String dbPassword2 = PasswordTools.encrypt(password);
        String dbPassword3 = PasswordTools.encrypt(password);

        System.out.println(dbPassword1);
        System.out.println(dbPassword2);
        System.out.println(dbPassword3);
        System.out.println("=======================================================");

        System.out.println(PasswordTools.decrypt("12345", dbPassword1));
        System.out.println(PasswordTools.decrypt(password, dbPassword2));
        System.out.println(PasswordTools.decrypt(password, dbPassword3));
    }
}
